package com.prs.crm.context;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.log4j.Logger;
import org.apache.struts2.ServletActionContext;

import com.prs.crm.domain.Attachment;
import com.prs.crm.domain.doc.FileType;

public class FileUtil {
	
	private final static Logger logger = Logger.getLogger(FileUtil.class);

	private final String FOLDER_DOC = "doc";
	
	private final String FOLDER_IMG = "img";
	
	private final String FOLDER_OTHER = "other";
	
	private static FileUtil util;
	
	private static List<String> docTypes;
	
	private static List<String> imgTypes;
	
	
	private static List<String> allowedExtensions;
	
	private static Map<String, String> mapType;
	
	static
	{
		docTypes = Arrays.asList("doc","docx","xls","xlsx","txt");
		imgTypes = Arrays.asList("jpg","jpeg","bmp","gif","png");
		allowedExtensions= Arrays.asList("doc","docx","xls","xlsx",
								"jpg","jpeg","bmp","gif","png","zip","rar","txt");
		mapType = new HashMap<String, String>();
		mapType.put("doc", "Word 文档");
		mapType.put("docx", "Word 文档");
		mapType.put("xls", "Excel 文档");
		mapType.put("xlsx", "Excel 文档");
		mapType.put("txt", "文本文档");
		mapType.put("jpg", "jpg 文件");
		mapType.put("jpeg", "jpeg 文件");
		mapType.put("bmp", "bmp 文件");
		mapType.put("gif", "gif 文件");
		mapType.put("png", "png 文件");
		mapType.put("zip", "zip 压缩包");
		mapType.put("rar", "rar 压缩包");
	}
	
	public static void setAllowedExtensions(List<String> arg)
	{
		allowedExtensions = arg;
	}
	
	

	
	public static FileUtil getInstance()	
	{
		if (util==null)
		{
			util = new FileUtil();
		}
		return util;
	}
	
	public  Collection<Attachment> createAttach(File[] files,String[] fileNames)
	{
		List<Attachment> attachs = new ArrayList<Attachment>();
		if (files!=null)
		{
			for (int i=0;i<files.length;i++)
			{
				Attach at = this.saveFile(files[i], fileNames[i], "", Constrains.UPLOAD_DIR);
				String type=at.getName().substring(at.getName().lastIndexOf('.')+1);
				Attachment attach = new Attachment();
				attach.setPath(at.getSrc());
				attach.setName(at.getName());
				attach.setContentType(type);
				attachs.add(attach);
			}
		}
		return attachs;
	}
	
	
	public  Attachment createAttach(File file,String fileName)
	{
		if (file!=null)
		{
			Attach at = this.saveFile(file, fileName, "", Constrains.UPLOAD_DIR);
			Attachment attach = new Attachment();
			String type=at.getName().substring(at.getName().lastIndexOf('.')+1);
			long i=file.length();
			attach.setPath(at.getSrc());
			attach.setName(at.getName());
			attach.setContentType(type);
			long a=i/1024;
			int b=(new Long(a).intValue())+1;
			String c=Long.toString((long)b);
			attach.setSize(c+"KB");
			return attach;
		}
		else
		{
			return null;
		}
		
	}
	public  Attachment createAttach1(File file,String fileName)
	{
		if (file!=null)
		{
			Attach at = this.saveFile(file, fileName, "", Constrains.UPLOAD_DIR);
			Attachment attach = new Attachment();
			String type=at.getName().substring(at.getName().lastIndexOf('.')+1);
			long i=file.length();
			attach.setPath(at.getPath());
			attach.setName(at.getName());
			attach.setContentType(type);
			long a=i/1024;
			int b=(new Long(a).intValue())+1;
			String c=Long.toString((long)b);
			attach.setSize(c+"KB");
			return attach;
		}
		else
		{
			return null;
		}
		
	}
	public  Attachment createAttachs(File file,String fileName,String contentType)
	{
		if (file!=null)
		{
			Attach at = this.saveFile(file, fileName, contentType, Constrains.UPLOAD_DIR);
			Attachment attach = new Attachment();
			String type=at.getName().substring(at.getName().lastIndexOf('.')+1);
			System.out.println(type);
			attach.setPath(at.getPath());
			attach.setName(at.getName());
			attach.setContentType(type);
			System.out.println(at.getContentType());
			return attach;
		}
		else
		{
			return null;
		}
		
	}
	/**
	 * 拷贝一个文件到指定目录
	 * @param file 
	 * @param filename
	 * @param contentType
	 * @param destdir 保存目录
	 * @return
	 */
	public  Attach saveFile(File file,String fileName,String contentType,String destdir)
	{
		return saveFile(file,fileName,contentType,destdir,true);
	}
	
	/**
	 * 保存文件到指定目录
	 * @param file
	 * @param fileName
	 * @param contentType
	 * @param destdir
	 * @param isDeleted 保存后是否删除原始文件
	 * @return
	 */
	public  Attach saveFile(File file,String fileName,String contentType,String destdir,boolean isDeleted)
	{
		try
		{
			String extendname = FilenameUtils.getExtension((fileName!=null)?fileName
										:file.getPath());
			if (true)//(allowedExtensions.contains(extendname.toLowerCase()))
			{
				String  target = this.createPath(getRealPath(destdir)
								,getSubFolder((fileName!=null)?fileName:file.getPath()));
//				String targets=ServletActionContext.getServletContext().getRealPath("/");
				logger.debug(" copy "+file.getPath()+" to "+target);
				File cpfile = copyFile(file,target,fileName);
				Attach attach = new Attach(cpfile);
				attach.setContentType(contentType);	
				attach.setName(FilenameUtils.getName(cpfile.getPath()));
				String type=attach.getName().substring(attach.getName().lastIndexOf('.')+1);
				System.out.println(type);
				attach.setPath(cpfile.getPath());
				attach.setSrc(getRelativePath(cpfile.getPath()));
				return attach;
			}
			else
			{
				Attach attach = new Attach();
				attach.setName(fileName);
				attach.setSuccessed(false);
				attach.setMessage("denied fileExtension :"+extendname);
				return attach;
			}
		}
		catch (Exception e)
		{
			logger.error(e);
			Attach attach = new Attach();
			attach.setName(fileName);
			attach.setSuccessed(false);
			attach.setMessage(e.getMessage());
			return attach;
		}
	}
	
	/**
	 * 批量保存文件
	 * @param files
	 * @param fileNames
	 * @param contentTypes
	 * @param destdir 目的目录
	 * @return
	 */
	public Attach[] saveFiles(File[] files,String[] fileNames,String[] contentTypes,String destdir)
	{

		return saveFiles(files,fileNames,contentTypes,destdir,true);
	}
	
	/**
	 * 批量保存文件
	 * @param files
	 * @param fileNames
	 * @param contentTypes
	 * @param destdir
	 * @param isDeleted 保存后是否删除原始文件
	 * @return
	 */
	public Attach[] saveFiles(File[] files,String[] fileNames,String[] contentTypes,String destdir,boolean isDeleted)
	{
		Attach[] attachs = new Attach[files.length];
		Attach attach = null;
		for (int i=0;i<files.length;i++)
		{
			attach = this.saveFile(files[i], (fileNames!=null&&fileNames.length>0)?fileNames[i]:null,
					(contentTypes!=null&&contentTypes.length>0)?contentTypes[i]:null, destdir,isDeleted);
				
			if (attach!=null)
				attachs[i] = attach;
			else
			{
				attachs[i] = new Attach();
				attachs[i].setName((fileNames!=null&&fileNames.length>0)?fileNames[i]:files[i].getName());
				attachs[i].setSuccessed(false);
				attachs[i].setMessage("save file error");
				logger.error("save file error:"+files[i].getPath());
			}
		}
		return attachs;
	}
	
	public boolean deleteFile(String path)
	{
		String filepath = this.getRealPath(path);
		File file = new File(filepath);
		if (file.exists() && !file.isDirectory())
		{
			return file.delete();
		}
		else
		{
			return false;
		}
	}
	
	private String getSubFolder(String filename)
	{
		String extendname = FilenameUtils.getExtension(filename);
		if (docTypes.contains(extendname.toLowerCase()))
		{
			return FOLDER_DOC;
		}
		else if (imgTypes.contains(extendname.toLowerCase()))
		{
			return FOLDER_IMG;
		}
		else
		{
			return FOLDER_OTHER;
		}
		
	}
	
	/**
	 * 根据当前日期和类型，创建目录
	 * @param path
	 * @param type
	 * @return
	 */
	private String createPath(String path,String type)
	{
		String fullpath = path;
		String separator = getSeparator();
		if (fullpath.lastIndexOf(separator)!=fullpath.length()-1)
			fullpath += separator;
		fullpath += type+separator;
		File file = new File(fullpath);
		if (!file.exists())
			file.mkdirs();
		return fullpath;
	}
	
	/**
	 * 获取系统路径分隔符
	 * @return
	 */
	private String getSeparator()
	{
		if(System.getProperty("os.name").toUpperCase().indexOf("WINDOWS")>=0)
			return "\\";
		else
			return "/";
	}
	
	/**
	 * 拷贝文件
	 * @param file
	 * @param path
	 * @param filename 指定保存的文件名
	 * @return
	 */
	public static File  copyFile(File file,String targetpath,String filename) throws IOException
	{
		String fileName = ((filename!=null)?filename:FilenameUtils.getName(file.getPath())).toLowerCase();
		String nameWithoutExt=FilenameUtils.getBaseName(fileName).toLowerCase();
		//String nameWithoutExt = UUID.randomUUID().toString().replace("-", "");
		String ext=FilenameUtils.getExtension((filename!=null)?filename:file.getPath()).toLowerCase();
		File pathToSave=new File(targetpath,nameWithoutExt+"."+ext);
		int counter=1;
		while(pathToSave.exists()){
			fileName=nameWithoutExt+"("+counter+")"+"."+ext;
			pathToSave=new File(targetpath,fileName);
			counter++;
		}
		FileUtils.copyFile(file, pathToSave);
		return pathToSave;
	}
	
	
	private String getRelativePath(String path)
	{
		String contextPath = getApplicationContext().getRealPath("/");
		if (path.toLowerCase().indexOf(contextPath.toLowerCase())==0)
		{
			path = path.substring(path.toLowerCase().indexOf(contextPath.toLowerCase())
						+contextPath.length());
		}
		path = path.replace('\\', '/');
		if (path.charAt(0)!='/')
			path = "/"+path;
		return path;
	}
	
	private String getRealPath(String path)
	{
		String contextPath = getApplicationContext().getRealPath("/");
		if (path.toLowerCase().indexOf(contextPath.toLowerCase())<0)
		{
			return getApplicationContext().getRealPath(path);
		}
		else
		{
			return path;
		}
	}
	
	private ServletContext getApplicationContext()
	{
		 return ServletActionContext.getServletContext();
	}
	
	
	
	
	public FileType getFileType(String filename){
		if(filename != null && filename.trim().length() > 0){
			FileType ft = new FileType();
			String extendname = FilenameUtils.getExtension(filename);
			if(allowedExtensions.contains(extendname)){
				String name = mapType.get(extendname);
				ft.setName(name);
				return ft;
			}else{
				ft.setName("未知类型文件");
				return ft;
			}
		}
		return null;
	}
	
	
	
}
